<!--
 * @Description: upload-img
 * @Version: 0.0.1
 * @Author: hweilp
 * @use: import Upload from '@/components/Upload'
 * components: { Upload },
 * <Upload></Upload>
 -->
<template>
  <div class="upload-img">
    <div class="upload-list" v-for="(item,$index) in images" :key="$index" @dragstart="dragstart($index,$event)"
         @dragend="dragend($event)" @drop="drop($index,$event)" @dragover="dragover($event)" draggable="true">
      <img class="img-list" :src="item" alt="">
      <!-- 操作 start -->
      <div class="opr-wrapper">
        <span class="up-edit">
          <i :class="['el-icon-arrow-left', {'disabled': $index + 1 === 1}]" @click="handleMove(item, $index, -1)" v-if="multiples"></i>
          <i class="el-icon-zoom-in" @click="handlePreview(item)"></i>
          <i class="el-icon-delete" @click="handleRemoveImg(item, $index)"></i>
          <i :class="['el-icon-arrow-right', {'disabled': $index + 1 === images.length}]" @click="handleMove(item, $index, 1)"
             v-if="multiples"></i>
        </span>
      </div>
      <!-- 操作 end -->
    </div>
    <div class="big_box" @drop="drop($event)" @dragover="allowDrop($event)"></div>
    <div class="add-upload">
      <div :class="['opr-wrapper']">
        <input ref="filElem" accept="image/gif, image/jpeg, image/png, image/jpg" type="file" class="upload-file"
               @change="getFile" :disabled="isUploading" :multiple="multiples">
        <span :class="['up-add', { 'uploading' : isUploading } ]" @click="handleOpenFile">
          <i :class="[ isUploading ? 'el-icon-loading' : 'el-icon-plus']"></i>
        </span>
      </div>
    </div>
    <el-dialog :visible.sync="dialogVisible" append-to-body>
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  </div>
</template>

<script>
import axios from 'axios'
import { GetPictureUploadSignData } from '@/api/common'
export default {
  name: 'UploadImage',
  data () {
    return {
      targetIndex: 0,
      moveIndex: 0,
      images: [],
      uploadIndex: 0, // 多文件上传 index
      maltiplesImage: [], // 多文件上传集-之前
      maltiplesImages: [], // 多文件上传集-之后
      maltiplesImagesLength: 0, // 多文件上传 文件数
      uploadCount: 0, // 上传次数
      isUploading: false,
      dialogVisible: false,
      dialogImageUrl: '',
      multiples: true,
      errorNum: 0 // 提示错误次数
    }
  },
  props: {
    fileLists: {
      type: Array,
      default: () => []
    },
    multiple: {
      type: Boolean,
      default: () => true
    },
    memoryMaxSize: {
      // 内存大小
      type: Number,
      default: 10
    },
    limit: {
      type: Number,
      default: NaN
    },
    limitSize: {
      type: Object,
      default: () => {
        return {
          width: 0,
          height: 0
        }
      }
    },
    // 图片限制尺寸忽略范围
    limitSizeRange: {
      type: Number,
      default: 50
    }
  },
  watch: {
    'fileLists': function (params) {
      this.images = params
    },
    'limit': function (val) {
      this.multiples = val !== 1
    }
  },
  created () { },
  mounted () {
    if (this.fileLists) {
      this.images = this.fileLists
    }
    this.multiples = this.limit !== 1
  },
  methods: {
    upEmitValue (val) {
      if (this.limit === 1) {
        this.$emit('input', this.images[0])
      } else {
        let imgs = ''
        this.images.map(item => {
          imgs += item + ','
        })
        imgs = imgs.substring(imgs.length - 1, 0)
        this.$emit('input', imgs)
      }
    },
    getFile (file) {
      let files = file.target.files
      this.errorNum = 0
      this.uploadIndex = 0
      this.uploadCount = 0
      this.maltiplesImagesLength = 0
      this.maltiplesImage = []
      this.maltiplesImages = []
      if (files) {
        for (const key in files) {
          const file = files[key]
          if (file && file.type && file.type.indexOf('image') !== -1) {
            this.uploadIndex++
            let item = {
              name: file.name,
              lastModified: file.lastModified,
              index: this.uploadIndex
            }
            this.maltiplesImage.push(item)
            this.handleImgSize(file, () => {
              this.maltiplesImagesLength++
              this.getServiceSign(file, item)
            })
          }
        }
      }
    },
    handleImgSize (file, callback) {
      // 图片存储的大小单位为字节 kb mb
      let imgSize = file.size
      let limitSizeObj = this.limitSize
      const img = new Image()
      // 以字节多少比较
      const maxSize = this.memoryMaxSize * 1024 * 1024
      const imgSizeMb = (imgSize / 1024 / 1024).toFixed(2)
      if (imgSize > maxSize) {
        this.errorMsg(`上传图片大小为${imgSizeMb}M，超过${this.memoryMaxSize}M的限制，请重新上传...`)
        return
      }

      img.onload = () => {
        const width = img.width
        const height = img.height

        // if (limitSizeObj.width && Math.abs(width - limitSizeObj.width) >= this.limitSizeRange) {
        // } else if (limitSizeObj.height && Math.abs(height - limitSizeObj.height) >= this.limitSizeRange) {
        if (limitSizeObj.width && width - limitSizeObj.width > 0) {
          this.errorMsg(`上传的图片尺寸宽为${width}，不符合图片的要求，请重新上传...`)
        } else if (limitSizeObj.height && height - limitSizeObj.height > 0) {
          this.errorMsg(`上传的图片尺寸高为${height}，不符合图片的要求，请重新上传...`)
        } else {
          // 正常 后续操作
          callback()
        }
      }
      img.onerror = function () {
        this.$message.warning('图片尺寸不符合，请重新上传....')
      }
      img.src = window.URL.createObjectURL(file)
    },
    errorMsg (message, type = 'warning', duration = 3) {
      if (this.errorNum <= 0) {
        this.$message({
          message: message,
          type: type,
          duration: duration * 1000
        })
      }
      this.errorNum++
    },
    getServiceSign (file, item) {
      this.isUploading = true
      GetPictureUploadSignData().then(res => {
        const data = res.data
        const host = data.host
        let fileName = file.name
        let suffix = fileName.split('.')[1]
        const moment = new Date().getTime()
        fileName = `${moment}.${suffix}`
        const ossData = {
          'key': `${data.dir}/${fileName}`,
          'policy': data.policy,
          'OSSAccessKeyId': data.accessKeyId,
          'signature': data.signature
        }
        // 图片上传后前置域名
        const vistUrl = data.vistUrl

        this.ossUpload(host, file, ossData, vistUrl, item)
      }).catch(() => {
        this.isUploading = false
        this.removeInputFileValue()
      })
    },
    ossUpload (host, file, ossData, vistUrl, item) {
      let ossFormData = new FormData()
      for (const key in ossData) {
        ossFormData.append(key, ossData[key])
      }
      ossFormData.append('file', file)
      const url = vistUrl + ossData.key

      axios({
        url: host,
        method: 'POST',
        data: ossFormData,
        headers: { 'Content-Type': 'multipart/form-data' }
      }).then(res => {
        this.uploadCount++
        if (this.limit === 1) {
          this.images = []
          this.images.push(url)
          this.isUploading = false
        } else {
          // 多个上传
          // this.images.push(url)
          let items = item
          items.url = url
          this.maltiplesImages.push(items)

          if (this.maltiplesImagesLength === this.uploadCount) {
            this.isUploading = false
            this.maltiplesImage.forEach(item => {
              this.maltiplesImages.forEach(i => {
                if (item.index === i.index) {
                  this.images.push(i.url)
                }
              })
            })
          }
        }

        this.upEmitValue()
        this.removeInputFileValue()
      }).catch(errors => {
        this.uploadCount++
        this.removeInputFileValue()
        this.isUploading = false
        this.$message.error('上传失败！')
      })
    },
    handleOpenFile () {
      this.$refs.filElem.dispatchEvent(new MouseEvent('click'))
    },
    handleRemoveImg (item, index) {
      this.images.splice(index, 1)
      this.upEmitValue()
    },
    handleMove (item, index, type) {
      // 左移
      if (type === -1 && index !== 0) {
        this.images = this.swapArr(this.images, index, index - 1)
      }
      // 右移
      if (type === 1 && index + 1 < this.images.length) {
        this.images = this.swapArr(this.images, index, index + 1)
      }

      this.upEmitValue()
    },
    removeInputFileValue () {
      this.firstUpImgName = ''
      this.$refs.filElem.value = ''
    },
    handlePreview (item) {
      this.dialogImageUrl = item
      this.dialogVisible = true
    },
    // 拖拽
    dragstart (index) {
      let that = this
      that.moveIndex = index
    },
    dragover (event) {
      // 必须添加dragover事件，不然drop事件也无效
      event.preventDefault()
    },
    dragend (event) {
    },
    drop (index, event) {
      var that = this
      // 阻止默认行为
      event.preventDefault()
      // 阻止默认行为
      event.stopPropagation()
      that.targetIndex = index
      this.images = this.swapArr(this.images, this.targetIndex, this.moveIndex)
      this.upEmitValue()
    },
    allowDrop: function (event) {
      event.preventDefault()
    },
    // 更换元素位置
    swapArr (arr, index1, index2) {
      arr[index1] = arr.splice(index2, 1, arr[index1])[0]
      return arr
    }
  }
}
</script>
